#pragma once
#include "../mqcommon/Log.hpp"
#include "../mqcommon/Helper.hpp"
#include "../mqcommon/Message.pb.h"

#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <functional>
#include <unordered_map>
#include <mutex>

namespace ouyangmq
{
    using ConsumerCallBack = std::function<void(const std::string &, const ouyangmq::BasicProperties *, const std::string &)>;
    // 消费者结构对象
    struct Consumer
    {
        using ptr = std::shared_ptr<Consumer>;
        // 1. 消费者标识
        std::string tag;
        // 2. 消费者订阅的队列名称
        std::string qname;
        // 3. 自动确认标识
        bool auto_ack;
        // 4. 回调函数 --> 队列有一条消息后，通过哪个函数进行处理
        ConsumerCallBack callbackfunc;

        Consumer() {}
        Consumer(const std::string &ctag, const std::string &queue_name, bool ack_flag, const ConsumerCallBack &cb)
            : tag(ctag), qname(queue_name), auto_ack(ack_flag), callbackfunc(cb)
        {
        }
    };

    // 以队列为单元管理的消费者结构
    class QueueConsumer
    {
    public:
        using ptr = std::shared_ptr<QueueConsumer>;
        QueueConsumer(const std::string &qname)
            : _qname(qname), _rr_seq(0)
        {
        }
        // 1. 队列新增消费者 -->这边返回值为消费者智能指针方便建立链接
        Consumer::ptr create(const std::string &ctag, const std::string &queue_name, bool ack_flag, const ConsumerCallBack &cb)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            // [1] 遍历原来的_consumers是否存在该消费者, 存在就直接返回
            for (auto &consumer : _consumers)
            {
                if (consumer->tag == ctag)
                    return Consumer::ptr();
            }
            // [2] 构造指定消费者, 插入到_consumers, 最后返回
            Consumer::ptr consumer = std::make_shared<Consumer>(ctag, queue_name, ack_flag, cb);
            _consumers.push_back(consumer);
            return consumer;
        }
        // 2. 移除队列的消费者
        void remove(const std::string &ctag)
        {
            // 1. 加锁
            std::unique_lock<std::mutex> lock(_mutex);
            // 2. 遍历查找-删除
            for (auto it = _consumers.begin(); it != _consumers.end(); ++it)
            {
                if ((*it)->tag == ctag)
                {
                    _consumers.erase(it);
                    return;
                }
            }
            return;
        }
        // 3. 获取队列消费者 --> RR轮转制
        Consumer::ptr choose()
        {
            // 1. 加锁
            std::unique_lock<std::mutex> lock(_mutex);
            // 2. 如果消费者个数为0, 返回空对象
            if (_consumers.size() == 0)
                return Consumer::ptr();
            // 3. 获取当前轮转的下标
            int index = _rr_seq % _consumers.size();
            ++_rr_seq;
            // 4. 返回对象
            return _consumers[index];
        }

        // 4. 判断管理消费者智能指针的数组是否为空
        bool empty()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _consumers.empty();
        }

        // 5. 查看指定消费者是否存在
        bool exists(const std::string &ctag)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            for (auto &consumer : _consumers)
            {
                if (consumer->tag == ctag)
                    return true;
            }
            return false;
        }
        // 6. 清理所有消费者
        void clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _qname.clear();
            _rr_seq = 0;
            _consumers.clear();
        }

    private:
        // 队列名称
        std::string _qname;
        // 互斥锁
        std::mutex _mutex;
        // 轮转序号
        uint64_t _rr_seq;
        // 管理消费者智能指针的数组
        std::vector<Consumer::ptr> _consumers;
    };

    class ConsumerManager
    {
    public:
        using ptr = std::shared_ptr<ConsumerManager>;   
        ConsumerManager(){};
        
        // 初始化队列消费者结构
        void InitQueueConsumer(const std::string &qname)
        {
            // 1. 加锁
            std::unique_lock<std::mutex> lock(_mutex);
            // 2. 重复判断
            auto it = _consumermanagers.find(qname);
            if (it != _consumermanagers.end())
                return;
            // 3. 初始化新增
            QueueConsumer::ptr qc = std::make_shared<QueueConsumer>(qname);
            _consumermanagers.emplace(qname, qc);
            // LogModule::LOG(LogModule::LogLevel::DEBUG) << "初始化队列 " << qname;
        }

        // 销毁队列消费者结构
        void DestoryQueueConsumer(const std::string &qname)
        {
            // 1. 加锁
            std::unique_lock<std::mutex> lock(_mutex);
            _consumermanagers.erase(qname);
        }

        Consumer::ptr AddConsumer(const std::string &ctag, const std::string &queue_name, bool ack_flag, const ConsumerCallBack &cb)
        {
            QueueConsumer::ptr qcp;
            {
                // 1. 加锁
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _consumermanagers.find(queue_name);
                if (it == _consumermanagers.end())
                {
                    LogModule::LOG(LogModule::LogLevel::ERROR) << "没有找到对应的队列句柄" << qname;
                    return Consumer::ptr();
                }
                qcp = it->second;
            }
            return qcp->create(ctag, queue_name, ack_flag, cb);
        }

        void RemoveConsumer(const std::string &ctag, const std::string &qname)
        {
            QueueConsumer::ptr qcp;
            {
                // 1. 加锁
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _consumermanagers.find(qname);
                if (it == _consumermanagers.end())
                {
                    LogModule::LOG(LogModule::LogLevel::ERROR) << "没有找到对应的消费者管理句柄" << qname;
                    return;
                }
                qcp = it->second;
            }
            return qcp->remove(ctag);
        }

        // RR轮转选出消费者
        Consumer::ptr Choose(const std::string &qname)
        {
            QueueConsumer::ptr qcp;
            {
                // 1. 加锁
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _consumermanagers.find(qname);
                if (it == _consumermanagers.end())
                {
                    LogModule::LOG(LogModule::LogLevel::ERROR) << "没有找到对应的消费者管理句柄" << qname;
                    return Consumer::ptr();
                }
                qcp = it->second;
            }
            return qcp->choose();
        }

        bool empty(const std::string &qname)
        {
            QueueConsumer::ptr qcp;
            {
                // 1. 加锁
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _consumermanagers.find(qname);
                if (it == _consumermanagers.end())
                {
                    LogModule::LOG(LogModule::LogLevel::ERROR) << "没有找到对应的消费者管理句柄" << qname;
                    return false;
                }
                qcp = it->second;
            }
            return qcp->empty();
        }

        bool exists(const std::string &ctag, const std::string &qname)
        {
            QueueConsumer::ptr qcp;
            {
                // 1. 加锁
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _consumermanagers.find(qname);
                if (it == _consumermanagers.end())
                {
                    LogModule::LOG(LogModule::LogLevel::ERROR) << "没有找到对应的消费者管理句柄" << qname;
                    return false;
                }
                qcp = it->second;
            }
            return qcp->exists(ctag);
        }

        void clear()
        {
            // 1. 加锁
            std::unique_lock<std::mutex> lock(_mutex);
            _consumermanagers.clear();
        }

    private:
        std::mutex _mutex;
        std::string qname;
        std::unordered_map<std::string, QueueConsumer::ptr> _consumermanagers; // qname和对应句柄的映射
    };
}